@@ -1083,7 +1083,6 @@ def __init__(
10831083 self .trace = self .pluginmanager .trace .root .get ("config" )
10841084 self .hook : pluggy .HookRelay = PathAwareHookProxy (self .pluginmanager .hook ) # type: ignore[assignment]
10851085 self ._inicache : dict [str , Any ] = {}
1086- self ._override_ini : Sequence [str ] = ()
10871086 self ._opt2dest : dict [str , str ] = {}
10881087 self ._cleanup_stack = contextlib .ExitStack ()
10891088 self .pluginmanager .register (self , "pytestconfig" )
@@ -1251,6 +1250,7 @@ def _initini(self, args: Sequence[str]) -> None:
12511250 )
12521251 rootpath , inipath , inicfg , ignored_config_files = determine_setup (
12531252 inifile = ns .inifilename ,
1253+ override_ini = ns .override_ini ,
12541254 args = ns .file_or_dir + unknown_args ,
12551255 rootdir_cmd_arg = ns .rootdir or None ,
12561256 invocation_dir = self .invocation_params .dir ,
@@ -1272,7 +1272,6 @@ def _initini(self, args: Sequence[str]) -> None:
12721272 type = "args" ,
12731273 default = [],
12741274 )
1275- self ._override_ini = ns .override_ini or ()
12761275
12771276 def _consider_importhook (self , args : Sequence [str ]) -> None :
12781277 """Install the PEP 302 import hook if using assertion rewriting.
@@ -1462,7 +1461,8 @@ def pytest_collection(self) -> Generator[None, object, object]:
14621461 def _checkversion (self ) -> None :
14631462 import pytest
14641463
1465- minver = self .inicfg .get ("minversion" , None )
1464+ minver_ini_value = self .inicfg .get ("minversion" , None )
1465+ minver = minver_ini_value .value if minver_ini_value is not None else None
14661466 if minver :
14671467 # Imported lazily to improve start-up time.
14681468 from packaging .version import Version
@@ -1520,9 +1520,9 @@ def _warn_or_fail_if_strict(self, message: str) -> None:
15201520
15211521 self .issue_config_time_warning (PytestConfigWarning (message ), stacklevel = 3 )
15221522
1523- def _get_unknown_ini_keys (self ) -> list [str ]:
1524- parser_inicfg = self ._parser ._inidict
1525- return [ name for name in self .inicfg if name not in parser_inicfg ]
1523+ def _get_unknown_ini_keys (self ) -> set [str ]:
1524+ known_keys = self ._parser ._inidict . keys () | self . _parser . _ini_aliases . keys ()
1525+ return self .inicfg . keys () - known_keys
15261526
15271527 def parse (self , args : list [str ], addopts : bool = True ) -> None :
15281528 # Parse given cmdline arguments into this config object.
@@ -1622,10 +1622,11 @@ def getini(self, name: str) -> Any:
16221622 :func:`parser.addini <pytest.Parser.addini>` call (usually from a
16231623 plugin), a ValueError is raised.
16241624 """
1625+ canonical_name = self ._parser ._ini_aliases .get (name , name )
16251626 try :
1626- return self ._inicache [name ]
1627+ return self ._inicache [canonical_name ]
16271628 except KeyError :
1628- self ._inicache [name ] = val = self ._getini (name )
1629+ self ._inicache [canonical_name ] = val = self ._getini (canonical_name )
16291630 return val
16301631
16311632 # Meant for easy monkeypatching by legacypath plugin.
@@ -1637,18 +1638,32 @@ def _getini_unknown_type(self, name: str, type: str, value: object):
16371638 raise ValueError (msg ) # pragma: no cover
16381639
16391640 def _getini (self , name : str ):
1641+ # If this is an alias, resolve to canonical name.
1642+ canonical_name = self ._parser ._ini_aliases .get (name , name )
1643+
16401644 try :
1641- _description , type , default = self ._parser ._inidict [name ]
1645+ _description , type , default = self ._parser ._inidict [canonical_name ]
16421646 except KeyError as e :
16431647 raise ValueError (f"unknown configuration value: { name !r} " ) from e
1644- override_value = self ._get_override_ini_value (name )
1645- if override_value is None :
1646- try :
1647- value = self .inicfg [name ]
1648- except KeyError :
1649- return default
1650- else :
1651- value = override_value
1648+
1649+ # Collect all possible values (canonical name + aliases) from inicfg.
1650+ # Each candidate is (IniValue, is_canonical).
1651+ candidates = []
1652+ if canonical_name in self .inicfg :
1653+ candidates .append ((self .inicfg [canonical_name ], True ))
1654+ for alias , target in self ._parser ._ini_aliases .items ():
1655+ if target == canonical_name and alias in self .inicfg :
1656+ candidates .append ((self .inicfg [alias ], False ))
1657+
1658+ if not candidates :
1659+ return default
1660+
1661+ # Pick the best candidate based on precedence:
1662+ # 1. CLI override takes precedence over file, then
1663+ # 2. Canonical name takes precedence over alias.
1664+ ini_value = max (candidates , key = lambda x : (x [0 ].origin == "override" , x [1 ]))[0 ]
1665+ value = ini_value .value
1666+
16521667 # Coerce the values based on types.
16531668 #
16541669 # Note: some coercions are only required if we are reading from .ini files, because
@@ -1719,23 +1734,6 @@ def _getconftest_pathlist(
17191734 values .append (relroot )
17201735 return values
17211736
1722- def _get_override_ini_value (self , name : str ) -> str | None :
1723- value = None
1724- # override_ini is a list of "ini=value" options.
1725- # Always use the last item if multiple values are set for same ini-name,
1726- # e.g. -o foo=bar1 -o foo=bar2 will set foo to bar2.
1727- for ini_config in self ._override_ini :
1728- try :
1729- key , user_ini_value = ini_config .split ("=" , 1 )
1730- except ValueError as e :
1731- raise UsageError (
1732- f"-o/--override-ini expects option=value style (got: { ini_config !r} )."
1733- ) from e
1734- else :
1735- if key == name :
1736- value = user_ini_value
1737- return value
1738-
17391737 def getoption (self , name : str , default : Any = notset , skip : bool = False ):
17401738 """Return command line option value.
17411739
0 commit comments