Coverage for .tox/testcoverage/lib/python2.7/site-packages/_pytest/config : 55%

Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
""" command line options, ini-file and conftest.py processing. """
# DON't import pytest here because it causes import cycle troubles
# pytest startup #
Exception.__init__(self, path, excinfo) self.path = path self.excinfo = excinfo
""" return exit code, after performing an in-process test run.
:arg args: list of command line arguments.
:arg plugins: list of plugin objects to be auto-registered during initialization. """ except ConftestImportFailure as e: tw = py.io.TerminalWriter(sys.stderr) for line in traceback.format_exception(*e.excinfo): tw.line(line.rstrip(), red=True) tw.line("ERROR: could not load %s\n" % (e.path), red=True) return 4 else: finally: except UsageError as e: for msg in e.args: sys.stderr.write("ERROR: %s\n" %(msg,)) return 4
""" error in pytest usage or invocation"""
"mark main terminal runner python pdb unittest capture skipping " "tmpdir monkeypatch recwarn pastebin helpconfig nose assertion genscript " "junitxml resultlog doctest cacheprovider").split()
# subsequent calls to main will create a fresh instance
""" Obtain a new instance of the :py:class:`_pytest.config.PytestPluginManager`, with default plugins already loaded.
This function can be used by integration with other tools, like hooking into pytest to run tests into an IDE. """ return get_config().pluginmanager
elif isinstance(args, py.path.local): args = [str(args)] elif not isinstance(args, (tuple, list)): if not isinstance(args, str): raise ValueError("not a string or argument list: %r" % (args,)) args = shlex.split(args) for plugin in plugins: if isinstance(plugin, py.builtin._basestring): pluginmanager.consider_pluginarg(plugin) else: pluginmanager.register(plugin) pluginmanager=pluginmanager, args=args) except BaseException: config._ensure_unconfigure() raise
""" Overwrites :py:class:`pluggy.PluginManager` to add pytest-specific functionality:
* loading plugins from the command line, ``PYTEST_PLUGIN`` env variable and ``pytest_plugins`` global variables found in plugins being loaded; * ``conftest.py`` loading during start-up; """
# state related to local conftest plugins
err = sys.stderr encoding = getattr(err, 'encoding', 'utf8') try: err = py.io.dupfile(err, encoding=encoding) except Exception: pass self.trace.root.setwriter(err.write) self.enable_tracing()
""" .. deprecated:: 2.8
Use :py:meth:`pluggy.PluginManager.add_hookspecs` instead. """ warning = dict(code="I2", fslocation=_pytest._code.getfslineno(sys._getframe(1)), nodeid=None, message="use pluginmanager.add_hookspecs instead of " "deprecated addhooks() method.") self._warn(warning) return self.add_hookspecs(module_or_class)
# pytest hooks are always prefixed with pytest_ # so we avoid accessing possibly non-readable attributes # (see issue #1073) # ignore some historic special names which can not be hooks anyway
module_or_class, name) "historic": hasattr(method, "historic")}
fslineno = _pytest._code.getfslineno(hookmethod.function) warning = dict(code="I1", fslocation=fslineno, nodeid=None, message="%r hook uses deprecated __multicall__ " "argument" % (hook.name)) self._warn(warning)
kwargs=dict(plugin=plugin, manager=self))
# support deprecated naming because plugins (xdist e.g.) use it return self.get_plugin(name)
"""Return True if the plugin with the given name is registered.""" return bool(self.get_plugin(name))
# XXX now that the pluginmanager exposes hookimpl(tryfirst...) # we should remove tryfirst/trylast as markers "tryfirst: mark a hook implementation function such that the " "plugin machinery will try to call it first/as early as possible.") "trylast: mark a hook implementation function such that the " "plugin machinery will try to call it last/as late as possible.")
kwargs = message if isinstance(message, dict) else { 'code': 'I1', 'message': message, 'fslocation': None, 'nodeid': None, } self.hook.pytest_logwarning.call_historic(kwargs=kwargs)
# # internal API for local conftest plugin handling # """ load initial conftest files given a preparsed "namespace". As conftest files may add their own command line options which have arguments ('--my-opt somepath') we might get some false positives. All builtin and 3rd party plugins will have been loaded, however, so common options will not confuse our logic here. """ if namespace.confcutdir else None # remove node-id syntax path = path[:i] self._try_load_conftest(current)
# let's also consider test* subdirs self._getconftestmodules(x)
return [] else: # XXX these days we may rather want to use config.rootdir # and allow users to opt into looking into the rootdir parent # directories instead of requiring to specify confcutdir mod = self._importconftest(conftestpath) clist.append(mod)
try: return mod, getattr(mod, name) except AttributeError: continue
try: return self._conftestpath2mod[conftestpath] except KeyError: pkgpath = conftestpath.pypkgpath() if pkgpath is None: _ensure_removed_sysmodule(conftestpath.purebasename) try: mod = conftestpath.pyimport() except Exception: raise ConftestImportFailure(conftestpath, sys.exc_info())
self._conftest_plugins.add(mod) self._conftestpath2mod[conftestpath] = mod dirpath = conftestpath.dirpath() if dirpath in self._path2confmods: for path, mods in self._path2confmods.items(): if path and path.relto(dirpath) or path == dirpath: assert mod not in mods mods.append(mod) self.trace("loaded conftestmodule %r" %(mod)) self.consider_conftest(mod) return mod
# # API for bootstrapping plugin loading # #
if opt1 == "-p": self.consider_pluginarg(opt2)
if arg.startswith("no:"): name = arg[3:] self.set_blocked(name) if not name.startswith("pytest_"): self.set_blocked("pytest_" + name) else: self.import_plugin(arg)
if self.register(conftestmodule, name=conftestmodule.__file__): self.consider_module(conftestmodule)
if isinstance(spec, str): spec = spec.split(",") for import_spec in spec: self.import_plugin(import_spec)
# most often modname refers to builtin modules, e.g. "pytester", # "terminal" or "capture". Those plugins are registered under their # basename for historic purposes but must be imported with the # _pytest prefix. return else: importspec = modname except ImportError as e: new_exc = ImportError('Error importing plugin "%s": %s' % (modname, e)) # copy over name and path attributes for attr in ('name', 'path'): if hasattr(e, attr): setattr(new_exc, attr, getattr(e, attr)) raise new_exc except Exception as e: import pytest if not hasattr(pytest, 'skip') or not isinstance(e, pytest.skip.Exception): raise self._warn("skipped plugin %r: %s" %((modname, e.msg))) else:
""" Parser for command line arguments and ini-file values.
:ivar extra_info: dict of generic param -> value to display in case there's an error processing the command line arguments. """
""" get (or create) a named option Group.
:name: name of the option group. :description: long description for --help output. :after: name of other group, used for ordering --help output.
The returned group object has an ``addoption`` method with the same signature as :py:func:`parser.addoption <_pytest.config.Parser.addoption>` but will be shown in the respective group in the output of ``pytest. --help``. """
""" register a command line option.
:opts: option names, can be short or long options. :attrs: same attributes which the ``add_option()`` function of the `argparse library <http://docs.python.org/2/library/argparse.html>`_ accepts.
After command line parsing options are available on the pytest config object via ``config.option.NAME`` where ``NAME`` is usually set by passing a ``dest`` attribute, for example ``addoption("--long", dest="NAME", ...)``. """ self._anonymous.addoption(*opts, **attrs)
# bash like autocompletion for dirs (appending '/')
"""parses and returns a namespace object with known arguments at this point. """
"""parses and returns a namespace object with known arguments, and the remaining arguments unknown at this point. """
""" register an ini-file option.
:name: name of the ini-variable :type: type of the variable, can be ``pathlist``, ``args``, ``linelist`` or ``bool``. :default: default value if no ini-file option exists but is queried.
The value of ini-variables can be retrieved via a call to :py:func:`config.getini(name) <_pytest.config.Config.getini>`. """
""" Raised if an Argument instance is created with invalid or inconsistent arguments. """
self.msg = msg self.option_id = str(option)
if self.option_id: return "option %s: %s" % (self.option_id, self.msg) else: return self.msg
"""class that mimics the necessary behaviour of optparse.Option """ 'int': int, 'string': str, } # enable after some grace period for plugin writers
"""store parms in private vars for use in add_argument""" try: help = attrs['help'] if '%default' in help: warnings.warn( 'pytest now uses argparse. "%default" should be' ' changed to "%(default)s" ', FutureWarning, stacklevel=3) except KeyError: pass else: # this might raise a keyerror as well, don't want to catch that if typ == 'choice': if self.TYPE_WARN: warnings.warn( 'type argument to addoption() is a string %r.' ' For parsearg this is optional and when supplied ' ' should be a type.' ' (options: %s)' % (typ, names), FutureWarning, stacklevel=3) # argparse expects a type here take it from # the type of the first element attrs['type'] = type(attrs['choices'][0]) else: if self.TYPE_WARN: warnings.warn( 'type argument to addoption() is a string %r.' ' For parsearg this should be a type.' ' (options: %s)' % (typ, names), FutureWarning, stacklevel=3) attrs['type'] = Argument._typ_map[typ] # used in test_parseopt -> test_parse_defaultgetter self.type = attrs['type'] else: # attribute existence is tested in Config._processopt else: try: self.dest = self._short_opts[0][1:] except IndexError: raise ArgumentError( 'need a long or short option', self)
# update any attributes set by processopt #a = a.replace('%prog', '%(prog)s')
"""directly from optparse
might not be necessary as this is passed to argparse later on""" raise ArgumentError( "invalid option string %r: " "must be at least two characters long" % opt, self) raise ArgumentError( "invalid short option string %r: " "must be of the form -x, (x any non-dash char)" % opt, self) else: raise ArgumentError( "invalid long option string %r: " "must start with --, followed by non-dash" % opt, self)
retval = 'Argument(' if self._short_opts: retval += '_short_opts: ' + repr(self._short_opts) + ', ' if self._long_opts: retval += '_long_opts: ' + repr(self._long_opts) + ', ' retval += 'dest: ' + repr(self.dest) + ', ' if hasattr(self, 'type'): retval += 'type: ' + repr(self.type) + ', ' if hasattr(self, 'default'): retval += 'default: ' + repr(self.default) + ', ' if retval[-2:] == ', ': # always long enough to test ("Argument(" ) retval = retval[:-2] retval += ')' return retval
""" add an option to this group.
if a shortened version of a long option is specified it will be suppressed in the help. addoption('--twowords', '--two-words') results in help showing '--two-words' only, but --twowords gets accepted **and** the automatic destination is in args.twowords """
if opt[0] == '-' and opt[1].islower(): raise ValueError("lowercase shortoptions reserved")
add_help=False, formatter_class=DropShorterLongHelpFormatter) # extra_info is a dict of (param -> value) to display if there's # an usage error to provide more contextual information to the user
"""allow splitting of positional arguments""" for arg in argv: if arg and arg[0] == '-': lines = ['unrecognized arguments: %s' % (' '.join(argv))] for k, v in sorted(self.extra_info.items()): lines.append(' %s: %s' % (k, v)) self.error('\n'.join(lines)) getattr(args, FILE_OR_DIR).extend(argv)
"""shorten help for long options that differ only in extra hyphens
- collapse **long** options that are the same except for extra hyphens - special action attribute map_long_option allows surpressing additional long options - shortcut if there are only two options and one of them is a short one - cache result on action object as this is called at least 2 times """ orgstr = argparse.HelpFormatter._format_action_invocation(self, action) if orgstr and orgstr[0] != '-': # only optional arguments return orgstr res = getattr(action, '_formatted_action_invocation', None) if res: return res options = orgstr.split(', ') if len(options) == 2 and (len(options[0]) == 2 or len(options[1]) == 2): # a shortcut for '-h, --help' or '--abc', '-a' action._formatted_action_invocation = orgstr return orgstr return_list = [] option_map = getattr(action, 'map_long_option', {}) if option_map is None: option_map = {} short_long = {} for option in options: if len(option) == 2 or option[2] == ' ': continue if not option.startswith('--'): raise ArgumentError('long optional argument without "--": [%s]' % (option), self) xxoption = option[2:] if xxoption.split()[0] not in option_map: shortened = xxoption.replace('-', '') if shortened not in short_long or \ len(short_long[shortened]) < len(xxoption): short_long[shortened] = xxoption # now short_long has been filled out to the longest with dashes # **and** we keep the right option ordering from add_argument for option in options: # if len(option) == 2 or option[2] == ' ': return_list.append(option) if option[2:] == short_long.get(option.replace('-', '')): return_list.append(option.replace(' ', '=')) action._formatted_action_invocation = ', '.join(return_list) return action._formatted_action_invocation
try: del sys.modules[modname] except KeyError: pass
""" holds cmdline options as attributes.""" return "<CmdOptions %r>" %(self.__dict__,)
return "<NOTSET>"
""" access to configuration values, pluginmanager and plugin hooks. """
#: access to command line option as attributes. #: (deprecated), use :py:func:`getoption() <_pytest.config.Config.getoption>` instead usage="%%(prog)s [options] [%s] [%s] [...]" % (_a, _a), processopt=self._processopt, ) #: a pluginmanager instance
""" Add a function to be called when the config object gets out of use (usually coninciding with pytest_unconfigure)."""
""" generate a warning for this test session. """ self.hook.pytest_logwarning.call_historic(kwargs=dict( code=code, message=message, fslocation=fslocation, nodeid=None))
return self.pluginmanager.get_plugin("terminalreporter")._tw
# REF1 assert self == pluginmanager.config, (self, pluginmanager.config)
if option and option.fulltrace: style = "long" else: style = "native" excrepr = excinfo.getrepr(funcargs=True, showlocals=getattr(option, 'showlocals', False), style=style, ) res = self.hook.pytest_internalerror(excrepr=excrepr, excinfo=excinfo) if not py.builtin.any(res): for line in str(excrepr).split("\n"): sys.stderr.write("INTERNALERROR> %s\n" %line) sys.stderr.flush()
# nodeid's are relative to the rootpath, compute relative to cwd if self.invocation_dir != self.rootdir: fullpath = self.rootdir.join(nodeid) nodeid = self.invocation_dir.bestrelpath(fullpath) return nodeid
def fromdictargs(cls, option_dict, args): """ constructor useable for subprocesses. """ config = get_config() config.option.__dict__.update(option_dict) config.parse(args, addopts=False) for x in config.option.plugins: config.pluginmanager.consider_pluginarg(x) return config
def pytest_load_initial_conftests(self, early_config):
except ImportError as e: self.warn("I2", "could not load setuptools entry import: %s" % (e,)) args=args, parser=self._parser) except ConftestImportFailure: e = sys.exc_info()[1] if ns.help or ns.version: # we don't want to prevent --help/--version to work # so just let is pass and print a warning at the end self._warn("could not load initial conftests (%s)\n" % e.path) else: raise
ver = minver.split(".") myver = pytest.__version__.split(".") if myver < ver: raise pytest.UsageError( "%s:%d: requires pytest-%s, actual pytest-%s'" %( self.inicfg.config.path, self.inicfg.lineof('minversion'), minver, pytest.__version__))
# parse given cmdline arguments into this config object. "can only parse cmdline args at most once per Config object") kwargs=dict(pluginmanager=self.pluginmanager)) # XXX deprecated hook: cwd = os.getcwd() if cwd == self.rootdir: args = self.getini('testpaths') if not args: args = [cwd]
""" add a line to an ini-file option. The option must have been declared but might not yet be set in which case the line becomes the the first line in its value. """
""" return configuration value from an :ref:`ini file <inifiles>`. If the specified name hasn't been registered through a prior :py:func:`parser.addini <pytest.config.Parser.addini>` call (usually from a plugin), a ValueError is raised. """
except KeyError: raise ValueError("unknown configuration value: %r" %(name,)) return '' dp = py.path.local(self.inicfg.config.path).dirpath() l = [] for relpath in shlex.split(value): l.append(dp.join(relpath, abs=True)) return l elif type == "linelist": return [t for t in map(lambda x: x.strip(), value.split("\n")) if t] elif type == "bool": return bool(_strtobool(value.strip())) else: assert type is None return value
modpath = py.path.local(mod.__file__).dirpath() l = [] for relroot in relroots: if not isinstance(relroot, py.path.local): relroot = relroot.replace("/", py.path.local.sep) relroot = modpath.join(relroot, abs=True) l.append(relroot) return l
""" return command line option value.
:arg name: name of the option. You may also specify the literal ``--OPT`` option instead of the "dest" option name. :arg default: default value if no option of that name exists. :arg skip: if True raise pytest.skip if option does not exists or has a None value. """ raise AttributeError(name) except AttributeError: if default is not notset: return default if skip: import pytest pytest.skip("no %r option found" %(name,)) raise ValueError("no option named %r" % (name,))
""" (deprecated, use getoption()) """
""" (deprecated, use getoption(skip=True)) """ return self.getoption(name, skip=True)
except ignore: return False
args = [py.path.local()] elif inibasename == "pytest.ini": # allowed to be empty return base, p, {} return None, None, None
# args are what we get after early command line parsing (usually # strings, but can be py.path.local objects as well) continue else: if p.relto(common_ancestor) or p == common_ancestor: continue elif common_ancestor.relto(p): common_ancestor = p else: shared = p.common(common_ancestor) if shared is not None: common_ancestor = shared common_ancestor = py.path.local() common_ancestor = common_ancestor.dirpath()
iniconfig = py.iniconfig.IniConfig(inifile) try: inicfg = iniconfig["pytest"] except KeyError: inicfg = None rootdir = get_common_ancestor(args) else: [ancestor], ["pytest.ini", "tox.ini", "setup.cfg"]) for rootdir in ancestor.parts(reverse=True): if rootdir.join("setup.py").exists(): break else: rootdir = ancestor
else: #if obj != pytest: # pytest.__all__.append(name)
"""Create a TerminalWriter instance configured according to the options in the config object. Every code which requires a TerminalWriter object and has access to a config object should use this function. """ tw.hasmarkup = True tw.hasmarkup = False
"""Convert a string representation of truth to true (1) or false (0).
True values are 'y', 'yes', 't', 'true', 'on', and '1'; false values are 'n', 'no', 'f', 'false', 'off', and '0'. Raises ValueError if 'val' is anything else.
.. note:: copied from distutils.util """ val = val.lower() if val in ('y', 'yes', 't', 'true', 'on', '1'): return 1 elif val in ('n', 'no', 'f', 'false', 'off', '0'): return 0 else: raise ValueError("invalid truth value %r" % (val,)) |