Skip to content

Commit 0553eb1

Browse files
committed
Implement PoC to allow the config to configure the load precedence.
1 parent e6e7c12 commit 0553eb1

File tree

3 files changed

+47
-2
lines changed

3 files changed

+47
-2
lines changed

news/1234.feature.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
The config precedence can now be overridden with a special ``config-precedence`` config value

src/pip/_internal/commands/configuration.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,7 @@ def list_config_values(self, options: Values, args: List[str]) -> None:
207207
write_output("%s, exists: %r", fname, file_exists)
208208
if file_exists:
209209
self.print_config_file_values(variant)
210+
write_output("load-precedence: %s", ", ".join(self.configuration.load_order))
210211

211212
def print_config_file_values(self, variant: Kind) -> None:
212213
"""Get key-value pairs from the file of a variant"""
@@ -216,7 +217,7 @@ def print_config_file_values(self, variant: Kind) -> None:
216217

217218
def print_env_var_values(self) -> None:
218219
"""Get key-values pairs present as environment variables"""
219-
write_output("%s:", "env_var")
220+
write_output("%s:", "env-var")
220221
with indent_log():
221222
for key, value in sorted(self.configuration.get_environ_vars()):
222223
env_var = f"PIP_{key.upper()}"

src/pip/_internal/configuration.py

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,8 @@ def __init__(self, isolated: bool, load_only: Optional[Kind] = None) -> None:
110110
self.isolated = isolated
111111
self.load_only = load_only
112112

113+
self._load_order: Tuple[Kind, ...] = OVERRIDE_ORDER
114+
113115
# Because we keep track of where we got the data from
114116
self._parsers: Dict[Kind, List[Tuple[str, RawConfigParser]]] = {
115117
variant: [] for variant in OVERRIDE_ORDER
@@ -125,6 +127,13 @@ def load(self) -> None:
125127
if not self.isolated:
126128
self._load_environment_vars()
127129

130+
@property
131+
def load_order(self) -> Tuple[Kind, ...]:
132+
# The act of computing the config dictionary will result in the _load_order
133+
# attribute being correctly updated.
134+
_ = self._dictionary
135+
return self._load_order
136+
128137
def get_file_to_edit(self) -> Optional[str]:
129138
"""Returns the file with highest priority in configuration"""
130139
assert self.load_only is not None, "Need to be specified a file to be editing"
@@ -225,11 +234,45 @@ def _ensure_have_load_only(self) -> None:
225234
@property
226235
def _dictionary(self) -> Dict[str, Any]:
227236
"""A dictionary representing the loaded configuration."""
237+
238+
# We always read the config in the default load-order first, giving
239+
# us a deterministic load-order configuration value.
240+
config = self._blended_config_dict(OVERRIDE_ORDER)
241+
242+
# Re-compose the config based on the desired override-order, if
243+
# different to the default.
244+
config_precedence: List[str] = (
245+
str(config.get("global.config-precedence", "")).strip().splitlines()
246+
)
247+
if config_precedence:
248+
bad_values = [
249+
value
250+
for value in config_precedence
251+
if value not in kinds.reverse_mapping
252+
]
253+
if bad_values:
254+
term_or_terms = "term" if len(bad_values) == 1 else "terms"
255+
raise ConfigurationError(
256+
f"Invalid config-precedence {term_or_terms} provided "
257+
f"({','.join(bad_values)}). "
258+
f"Valid values are {', '.join(map(repr, kinds.reverse_mapping))}."
259+
)
260+
self._load_order = tuple(
261+
getattr(kinds, kinds.reverse_mapping[value])
262+
for value in config_precedence
263+
)
264+
if self._load_order != OVERRIDE_ORDER:
265+
config = self._blended_config_dict(self._load_order)
266+
return config
267+
268+
def _blended_config_dict(
269+
self, load_order: Tuple[Kind, ...] = OVERRIDE_ORDER
270+
) -> Dict[str, Any]:
228271
# NOTE: Dictionaries are not populated if not loaded. So, conditionals
229272
# are not needed here.
230273
retval = {}
231274

232-
for variant in OVERRIDE_ORDER:
275+
for variant in load_order:
233276
retval.update(self._config[variant])
234277

235278
return retval

0 commit comments

Comments
 (0)