1818import enum
1919from functools import lru_cache
2020import glob
21+ import importlib
2122import importlib .metadata
2223import inspect
2324import os
5556from _pytest ._code .code import TracebackStyle
5657from _pytest ._io import TerminalWriter
5758from _pytest .compat import assert_never
59+ from _pytest .compat import NOTSET
5860from _pytest .config .argparsing import Argument
5961from _pytest .config .argparsing import FILE_OR_DIR
6062from _pytest .config .argparsing import Parser
@@ -873,7 +875,13 @@ def import_plugin(self, modname: str, consider_entry_points: bool = False) -> No
873875 return
874876
875877 try :
876- __import__ (importspec )
878+ if sys .version_info >= (3 , 11 ):
879+ mod = importlib .import_module (importspec )
880+ else :
881+ # On Python 3.10, import_module breaks
882+ # testing/test_config.py::test_disable_plugin_autoload.
883+ __import__ (importspec )
884+ mod = sys .modules [importspec ]
877885 except ImportError as e :
878886 raise ImportError (
879887 f'Error importing plugin "{ modname } ": { e .args [0 ]} '
@@ -882,7 +890,6 @@ def import_plugin(self, modname: str, consider_entry_points: bool = False) -> No
882890 except Skipped as e :
883891 self .skipped_plugins .append ((modname , e .msg or "" ))
884892 else :
885- mod = sys .modules [importspec ]
886893 self .register (mod , modname )
887894
888895
@@ -907,14 +914,6 @@ def _get_plugin_specs_as_list(
907914 )
908915
909916
910- class Notset :
911- def __repr__ (self ):
912- return "<NOTSET>"
913-
914-
915- notset = Notset ()
916-
917-
918917def _iter_rewritable_modules (package_files : Iterable [str ]) -> Iterator [str ]:
919918 """Given an iterable of file names in a source distribution, return the "names" that should
920919 be marked for assertion rewrite.
@@ -1090,7 +1089,6 @@ def __init__(
10901089 self .trace = self .pluginmanager .trace .root .get ("config" )
10911090 self .hook : pluggy .HookRelay = PathAwareHookProxy (self .pluginmanager .hook ) # type: ignore[assignment]
10921091 self ._inicache : dict [str , Any ] = {}
1093- self ._opt2dest : dict [str , str ] = {}
10941092 self ._cleanup_stack = contextlib .ExitStack ()
10951093 self .pluginmanager .register (self , "pytestconfig" )
10961094 self ._configured = False
@@ -1215,12 +1213,8 @@ def fromdictargs(cls, option_dict: Mapping[str, Any], args: list[str]) -> Config
12151213 return config
12161214
12171215 def _processopt (self , opt : Argument ) -> None :
1218- for name in opt ._short_opts + opt ._long_opts :
1219- self ._opt2dest [name ] = opt .dest
1220-
1221- if hasattr (opt , "default" ):
1222- if not hasattr (self .option , opt .dest ):
1223- setattr (self .option , opt .dest , opt .default )
1216+ if not hasattr (self .option , opt .dest ):
1217+ setattr (self .option , opt .dest , opt .default )
12241218
12251219 @hookimpl (trylast = True )
12261220 def pytest_load_initial_conftests (self , early_config : Config ) -> None :
@@ -1376,17 +1370,11 @@ def pytest_collection(self) -> Generator[None, object, object]:
13761370 def _checkversion (self ) -> None :
13771371 import pytest
13781372
1379- minver_ini_value = self .inicfg .get ("minversion" , None )
1380- minver = minver_ini_value .value if minver_ini_value is not None else None
1373+ minver = self .getini ("minversion" )
13811374 if minver :
13821375 # Imported lazily to improve start-up time.
13831376 from packaging .version import Version
13841377
1385- if not isinstance (minver , str ):
1386- raise pytest .UsageError (
1387- f"{ self .inipath } : 'minversion' must be a single value"
1388- )
1389-
13901378 if Version (minver ) > Version (pytest .__version__ ):
13911379 raise pytest .UsageError (
13921380 f"{ self .inipath } : 'minversion' requires pytest-{ minver } , actual pytest-{ pytest .__version__ } '"
@@ -1840,7 +1828,7 @@ def _getconftest_pathlist(
18401828 values .append (relroot )
18411829 return values
18421830
1843- def getoption (self , name : str , default : Any = notset , skip : bool = False ):
1831+ def getoption (self , name : str , default : Any = NOTSET , skip : bool = False ):
18441832 """Return command line option value.
18451833
18461834 :param name: Name of the option. You may also specify
@@ -1850,14 +1838,14 @@ def getoption(self, name: str, default: Any = notset, skip: bool = False):
18501838 :param skip: If ``True``, raise :func:`pytest.skip` if option is undeclared or has a ``None`` value.
18511839 Note that even if ``True``, if a default was specified it will be returned instead of a skip.
18521840 """
1853- name = self ._opt2dest .get (name , name )
1841+ name = self ._parser . _opt2dest .get (name , name )
18541842 try :
18551843 val = getattr (self .option , name )
18561844 if val is None and skip :
18571845 raise AttributeError (name )
18581846 return val
18591847 except AttributeError as e :
1860- if default is not notset :
1848+ if default is not NOTSET :
18611849 return default
18621850 if skip :
18631851 import pytest
@@ -2134,7 +2122,7 @@ def _resolve_warning_category(category: str) -> type[Warning]:
21342122 klass = category
21352123 else :
21362124 module , _ , klass = category .rpartition ("." )
2137- m = __import__ (module , None , None , [ klass ] )
2125+ m = importlib . import_module (module )
21382126 cat = getattr (m , klass )
21392127 if not issubclass (cat , Warning ):
21402128 raise UsageError (f"{ cat } is not a Warning subclass" )
0 commit comments