1313import types
1414import warnings
1515
16+ import attr
1617import py
1718import six
1819from packaging .version import Version
3536from _pytest .compat import safe_str
3637from _pytest .outcomes import fail
3738from _pytest .outcomes import Skipped
39+ from _pytest .pathlib import Path
3840from _pytest .warning_types import PytestConfigWarning
3941
4042hookimpl = HookimplMarker ("pytest" )
@@ -154,10 +156,15 @@ def directory_arg(path, optname):
154156builtin_plugins .add ("pytester" )
155157
156158
157- def get_config (args = None ):
159+ def get_config (args = None , plugins = None ):
158160 # subsequent calls to main will create a fresh instance
159161 pluginmanager = PytestPluginManager ()
160- config = Config (pluginmanager )
162+ config = Config (
163+ pluginmanager ,
164+ invocation_params = Config .InvocationParams (
165+ args = args , plugins = plugins , dir = Path ().resolve ()
166+ ),
167+ )
161168
162169 if args is not None :
163170 # Handle any "-p no:plugin" args.
@@ -190,7 +197,7 @@ def _prepareconfig(args=None, plugins=None):
190197 msg = "`args` parameter expected to be a list or tuple of strings, got: {!r} (type: {})"
191198 raise TypeError (msg .format (args , type (args )))
192199
193- config = get_config (args )
200+ config = get_config (args , plugins )
194201 pluginmanager = config .pluginmanager
195202 try :
196203 if plugins :
@@ -686,13 +693,52 @@ def _iter_rewritable_modules(package_files):
686693
687694
688695class Config (object ):
689- """ access to configuration values, pluginmanager and plugin hooks. """
696+ """
697+ Access to configuration values, pluginmanager and plugin hooks.
698+
699+ :ivar PytestPluginManager pluginmanager: the plugin manager handles plugin registration and hook invocation.
700+
701+ :ivar argparse.Namespace option: access to command line option as attributes.
702+
703+ :ivar InvocationParams invocation_params:
704+
705+ Object containing the parameters regarding the ``pytest.main``
706+ invocation.
707+ Contains the followinig read-only attributes:
708+ * ``args``: list of command-line arguments as passed to ``pytest.main()``.
709+ * ``plugins``: list of extra plugins, might be None
710+ * ``dir``: directory where ``pytest.main()`` was invoked from.
711+ """
712+
713+ @attr .s (frozen = True )
714+ class InvocationParams (object ):
715+ """Holds parameters passed during ``pytest.main()``
716+
717+ .. note::
718+
719+ Currently the environment variable PYTEST_ADDOPTS is also handled by
720+ pytest implicitly, not being part of the invocation.
721+
722+ Plugins accessing ``InvocationParams`` must be aware of that.
723+ """
724+
725+ args = attr .ib ()
726+ plugins = attr .ib ()
727+ dir = attr .ib ()
728+
729+ def __init__ (self , pluginmanager , invocation_params = None , * args ):
730+ from .argparsing import Parser , FILE_OR_DIR
731+
732+ if invocation_params is None :
733+ invocation_params = self .InvocationParams (
734+ args = (), plugins = None , dir = Path ().resolve ()
735+ )
690736
691- def __init__ (self , pluginmanager ):
692737 #: access to command line option as attributes.
693738 #: (deprecated), use :py:func:`getoption() <_pytest.config.Config.getoption>` instead
694739 self .option = argparse .Namespace ()
695- from .argparsing import Parser , FILE_OR_DIR
740+
741+ self .invocation_params = invocation_params
696742
697743 _a = FILE_OR_DIR
698744 self ._parser = Parser (
@@ -709,9 +755,13 @@ def __init__(self, pluginmanager):
709755 self ._cleanup = []
710756 self .pluginmanager .register (self , "pytestconfig" )
711757 self ._configured = False
712- self .invocation_dir = py .path .local ()
713758 self .hook .pytest_addoption .call_historic (kwargs = dict (parser = self ._parser ))
714759
760+ @property
761+ def invocation_dir (self ):
762+ """Backward compatibility"""
763+ return py .path .local (str (self .invocation_params .dir ))
764+
715765 def add_cleanup (self , func ):
716766 """ Add a function to be called when the config object gets out of
717767 use (usually coninciding with pytest_unconfigure)."""
0 commit comments