1""" command line options, ini-file and conftest.py processing. """
2import argparse
3import shlex
4import traceback
5import types
6import warnings
7
8import py
9# DON't import pytest here because it causes import cycle troubles
10import sys, os
11import _pytest._code
12import _pytest.hookspec  # the extension point definitions
13from _pytest._pluggy import PluginManager, HookimplMarker, HookspecMarker
14
15hookimpl = HookimplMarker("pytest")
16hookspec = HookspecMarker("pytest")
17
18# pytest startup
19#
20
21
22class ConftestImportFailure(Exception):
23    def __init__(self, path, excinfo):
24        Exception.__init__(self, path, excinfo)
25        self.path = path
26        self.excinfo = excinfo
27
28
29def main(args=None, plugins=None):
30    """ return exit code, after performing an in-process test run.
31
32    :arg args: list of command line arguments.
33
34    :arg plugins: list of plugin objects to be auto-registered during
35                  initialization.
36    """
37    try:
38        try:
39            config = _prepareconfig(args, plugins)
40        except ConftestImportFailure as e:
41            tw = py.io.TerminalWriter(sys.stderr)
42            for line in traceback.format_exception(*e.excinfo):
43                tw.line(line.rstrip(), red=True)
44            tw.line("ERROR: could not load %s\n" % (e.path), red=True)
45            return 4
46        else:
47            try:
48                config.pluginmanager.check_pending()
49                return config.hook.pytest_cmdline_main(config=config)
50            finally:
51                config._ensure_unconfigure()
52    except UsageError as e:
53        for msg in e.args:
54            sys.stderr.write("ERROR: %s\n" %(msg,))
55        return 4
56
57class cmdline:  # compatibility namespace
58    main = staticmethod(main)
59
60class UsageError(Exception):
61    """ error in pytest usage or invocation"""
62
63_preinit = []
64
65default_plugins = (
66     "mark main terminal runner python pdb unittest capture skipping "
67     "tmpdir monkeypatch recwarn pastebin helpconfig nose assertion genscript "
68     "junitxml resultlog doctest cacheprovider").split()
69
70builtin_plugins = set(default_plugins)
71builtin_plugins.add("pytester")
72
73
74def _preloadplugins():
75    assert not _preinit
76    _preinit.append(get_config())
77
78def get_config():
79    if _preinit:
80        return _preinit.pop(0)
81    # subsequent calls to main will create a fresh instance
82    pluginmanager = PytestPluginManager()
83    config = Config(pluginmanager)
84    for spec in default_plugins:
85        pluginmanager.import_plugin(spec)
86    return config
87
88def get_plugin_manager():
89    """
90    Obtain a new instance of the
91    :py:class:`_pytest.config.PytestPluginManager`, with default plugins
92    already loaded.
93
94    This function can be used by integration with other tools, like hooking
95    into pytest to run tests into an IDE.
96    """
97    return get_config().pluginmanager
98
99def _prepareconfig(args=None, plugins=None):
100    if args is None:
101        args = sys.argv[1:]
102    elif isinstance(args, py.path.local):
103        args = [str(args)]
104    elif not isinstance(args, (tuple, list)):
105        if not isinstance(args, str):
106            raise ValueError("not a string or argument list: %r" % (args,))
107        args = shlex.split(args)
108    config = get_config()
109    pluginmanager = config.pluginmanager
110    try:
111        if plugins:
112            for plugin in plugins:
113                if isinstance(plugin, py.builtin._basestring):
114                    pluginmanager.consider_pluginarg(plugin)
115                else:
116                    pluginmanager.register(plugin)
117        return pluginmanager.hook.pytest_cmdline_parse(
118                pluginmanager=pluginmanager, args=args)
119    except BaseException:
120        config._ensure_unconfigure()
121        raise
122
123
124class PytestPluginManager(PluginManager):
125    """
126    Overwrites :py:class:`pluggy.PluginManager` to add pytest-specific
127    functionality:
128
129    * loading plugins from the command line, ``PYTEST_PLUGIN`` env variable and
130      ``pytest_plugins`` global variables found in plugins being loaded;
131    * ``conftest.py`` loading during start-up;
132    """
133    def __init__(self):
134        super(PytestPluginManager, self).__init__("pytest", implprefix="pytest_")
135        self._conftest_plugins = set()
136
137        # state related to local conftest plugins
138        self._path2confmods = {}
139        self._conftestpath2mod = {}
140        self._confcutdir = None
141        self._noconftest = False
142
143        self.add_hookspecs(_pytest.hookspec)
144        self.register(self)
145        if os.environ.get('PYTEST_DEBUG'):
146            err = sys.stderr
147            encoding = getattr(err, 'encoding', 'utf8')
148            try:
149                err = py.io.dupfile(err, encoding=encoding)
150            except Exception:
151                pass
152            self.trace.root.setwriter(err.write)
153            self.enable_tracing()
154
155    def addhooks(self, module_or_class):
156        """
157        .. deprecated:: 2.8
158
159        Use :py:meth:`pluggy.PluginManager.add_hookspecs` instead.
160        """
161        warning = dict(code="I2",
162                       fslocation=_pytest._code.getfslineno(sys._getframe(1)),
163                       nodeid=None,
164                       message="use pluginmanager.add_hookspecs instead of "
165                               "deprecated addhooks() method.")
166        self._warn(warning)
167        return self.add_hookspecs(module_or_class)
168
169    def parse_hookimpl_opts(self, plugin, name):
170        # pytest hooks are always prefixed with pytest_
171        # so we avoid accessing possibly non-readable attributes
172        # (see issue #1073)
173        if not name.startswith("pytest_"):
174            return
175        # ignore some historic special names which can not be hooks anyway
176        if name == "pytest_plugins" or name.startswith("pytest_funcarg__"):
177            return
178
179        method = getattr(plugin, name)
180        opts = super(PytestPluginManager, self).parse_hookimpl_opts(plugin, name)
181        if opts is not None:
182            for name in ("tryfirst", "trylast", "optionalhook", "hookwrapper"):
183                opts.setdefault(name, hasattr(method, name))
184        return opts
185
186    def parse_hookspec_opts(self, module_or_class, name):
187        opts = super(PytestPluginManager, self).parse_hookspec_opts(
188                                                module_or_class, name)
189        if opts is None:
190            method = getattr(module_or_class, name)
191            if name.startswith("pytest_"):
192                opts = {"firstresult": hasattr(method, "firstresult"),
193                        "historic": hasattr(method, "historic")}
194        return opts
195
196    def _verify_hook(self, hook, hookmethod):
197        super(PytestPluginManager, self)._verify_hook(hook, hookmethod)
198        if "__multicall__" in hookmethod.argnames:
199            fslineno = _pytest._code.getfslineno(hookmethod.function)
200            warning = dict(code="I1",
201                           fslocation=fslineno,
202                           nodeid=None,
203                           message="%r hook uses deprecated __multicall__ "
204                                   "argument" % (hook.name))
205            self._warn(warning)
206
207    def register(self, plugin, name=None):
208        ret = super(PytestPluginManager, self).register(plugin, name)
209        if ret:
210            self.hook.pytest_plugin_registered.call_historic(
211                      kwargs=dict(plugin=plugin, manager=self))
212        return ret
213
214    def getplugin(self, name):
215        # support deprecated naming because plugins (xdist e.g.) use it
216        return self.get_plugin(name)
217
218    def hasplugin(self, name):
219        """Return True if the plugin with the given name is registered."""
220        return bool(self.get_plugin(name))
221
222    def pytest_configure(self, config):
223        # XXX now that the pluginmanager exposes hookimpl(tryfirst...)
224        # we should remove tryfirst/trylast as markers
225        config.addinivalue_line("markers",
226            "tryfirst: mark a hook implementation function such that the "
227            "plugin machinery will try to call it first/as early as possible.")
228        config.addinivalue_line("markers",
229            "trylast: mark a hook implementation function such that the "
230            "plugin machinery will try to call it last/as late as possible.")
231
232    def _warn(self, message):
233        kwargs = message if isinstance(message, dict) else {
234            'code': 'I1',
235            'message': message,
236            'fslocation': None,
237            'nodeid': None,
238        }
239        self.hook.pytest_logwarning.call_historic(kwargs=kwargs)
240
241    #
242    # internal API for local conftest plugin handling
243    #
244    def _set_initial_conftests(self, namespace):
245        """ load initial conftest files given a preparsed "namespace".
246            As conftest files may add their own command line options
247            which have arguments ('--my-opt somepath') we might get some
248            false positives.  All builtin and 3rd party plugins will have
249            been loaded, however, so common options will not confuse our logic
250            here.
251        """
252        current = py.path.local()
253        self._confcutdir = current.join(namespace.confcutdir, abs=True) \
254                                if namespace.confcutdir else None
255        self._noconftest = namespace.noconftest
256        testpaths = namespace.file_or_dir
257        foundanchor = False
258        for path in testpaths:
259            path = str(path)
260            # remove node-id syntax
261            i = path.find("::")
262            if i != -1:
263                path = path[:i]
264            anchor = current.join(path, abs=1)
265            if exists(anchor): # we found some file object
266                self._try_load_conftest(anchor)
267                foundanchor = True
268        if not foundanchor:
269            self._try_load_conftest(current)
270
271    def _try_load_conftest(self, anchor):
272        self._getconftestmodules(anchor)
273        # let's also consider test* subdirs
274        if anchor.check(dir=1):
275            for x in anchor.listdir("test*"):
276                if x.check(dir=1):
277                    self._getconftestmodules(x)
278
279    def _getconftestmodules(self, path):
280        if self._noconftest:
281            return []
282        try:
283            return self._path2confmods[path]
284        except KeyError:
285            if path.isfile():
286                clist = self._getconftestmodules(path.dirpath())
287            else:
288                # XXX these days we may rather want to use config.rootdir
289                # and allow users to opt into looking into the rootdir parent
290                # directories instead of requiring to specify confcutdir
291                clist = []
292                for parent in path.parts():
293                    if self._confcutdir and self._confcutdir.relto(parent):
294                        continue
295                    conftestpath = parent.join("conftest.py")
296                    if conftestpath.isfile():
297                        mod = self._importconftest(conftestpath)
298                        clist.append(mod)
299
300            self._path2confmods[path] = clist
301            return clist
302
303    def _rget_with_confmod(self, name, path):
304        modules = self._getconftestmodules(path)
305        for mod in reversed(modules):
306            try:
307                return mod, getattr(mod, name)
308            except AttributeError:
309                continue
310        raise KeyError(name)
311
312    def _importconftest(self, conftestpath):
313        try:
314            return self._conftestpath2mod[conftestpath]
315        except KeyError:
316            pkgpath = conftestpath.pypkgpath()
317            if pkgpath is None:
318                _ensure_removed_sysmodule(conftestpath.purebasename)
319            try:
320                mod = conftestpath.pyimport()
321            except Exception:
322                raise ConftestImportFailure(conftestpath, sys.exc_info())
323
324            self._conftest_plugins.add(mod)
325            self._conftestpath2mod[conftestpath] = mod
326            dirpath = conftestpath.dirpath()
327            if dirpath in self._path2confmods:
328                for path, mods in self._path2confmods.items():
329                    if path and path.relto(dirpath) or path == dirpath:
330                        assert mod not in mods
331                        mods.append(mod)
332            self.trace("loaded conftestmodule %r" %(mod))
333            self.consider_conftest(mod)
334            return mod
335
336    #
337    # API for bootstrapping plugin loading
338    #
339    #
340
341    def consider_preparse(self, args):
342        for opt1,opt2 in zip(args, args[1:]):
343            if opt1 == "-p":
344                self.consider_pluginarg(opt2)
345
346    def consider_pluginarg(self, arg):
347        if arg.startswith("no:"):
348            name = arg[3:]
349            self.set_blocked(name)
350            if not name.startswith("pytest_"):
351                self.set_blocked("pytest_" + name)
352        else:
353            self.import_plugin(arg)
354
355    def consider_conftest(self, conftestmodule):
356        if self.register(conftestmodule, name=conftestmodule.__file__):
357            self.consider_module(conftestmodule)
358
359    def consider_env(self):
360        self._import_plugin_specs(os.environ.get("PYTEST_PLUGINS"))
361
362    def consider_module(self, mod):
363        self._import_plugin_specs(getattr(mod, "pytest_plugins", None))
364
365    def _import_plugin_specs(self, spec):
366        if spec:
367            if isinstance(spec, str):
368                spec = spec.split(",")
369            for import_spec in spec:
370                self.import_plugin(import_spec)
371
372    def import_plugin(self, modname):
373        # most often modname refers to builtin modules, e.g. "pytester",
374        # "terminal" or "capture".  Those plugins are registered under their
375        # basename for historic purposes but must be imported with the
376        # _pytest prefix.
377        assert isinstance(modname, str)
378        if self.get_plugin(modname) is not None:
379            return
380        if modname in builtin_plugins:
381            importspec = "_pytest." + modname
382        else:
383            importspec = modname
384        try:
385            __import__(importspec)
386        except ImportError as e:
387            new_exc = ImportError('Error importing plugin "%s": %s' % (modname, e))
388            # copy over name and path attributes
389            for attr in ('name', 'path'):
390                if hasattr(e, attr):
391                    setattr(new_exc, attr, getattr(e, attr))
392            raise new_exc
393        except Exception as e:
394            import pytest
395            if not hasattr(pytest, 'skip') or not isinstance(e, pytest.skip.Exception):
396                raise
397            self._warn("skipped plugin %r: %s" %((modname, e.msg)))
398        else:
399            mod = sys.modules[importspec]
400            self.register(mod, modname)
401            self.consider_module(mod)
402
403
404class Parser:
405    """ Parser for command line arguments and ini-file values.
406
407    :ivar extra_info: dict of generic param -> value to display in case
408        there's an error processing the command line arguments.
409    """
410
411    def __init__(self, usage=None, processopt=None):
412        self._anonymous = OptionGroup("custom options", parser=self)
413        self._groups = []
414        self._processopt = processopt
415        self._usage = usage
416        self._inidict = {}
417        self._ininames = []
418        self.extra_info = {}
419
420    def processoption(self, option):
421        if self._processopt:
422            if option.dest:
423                self._processopt(option)
424
425    def getgroup(self, name, description="", after=None):
426        """ get (or create) a named option Group.
427
428        :name: name of the option group.
429        :description: long description for --help output.
430        :after: name of other group, used for ordering --help output.
431
432        The returned group object has an ``addoption`` method with the same
433        signature as :py:func:`parser.addoption
434        <_pytest.config.Parser.addoption>` but will be shown in the
435        respective group in the output of ``pytest. --help``.
436        """
437        for group in self._groups:
438            if group.name == name:
439                return group
440        group = OptionGroup(name, description, parser=self)
441        i = 0
442        for i, grp in enumerate(self._groups):
443            if grp.name == after:
444                break
445        self._groups.insert(i+1, group)
446        return group
447
448    def addoption(self, *opts, **attrs):
449        """ register a command line option.
450
451        :opts: option names, can be short or long options.
452        :attrs: same attributes which the ``add_option()`` function of the
453           `argparse library
454           <http://docs.python.org/2/library/argparse.html>`_
455           accepts.
456
457        After command line parsing options are available on the pytest config
458        object via ``config.option.NAME`` where ``NAME`` is usually set
459        by passing a ``dest`` attribute, for example
460        ``addoption("--long", dest="NAME", ...)``.
461        """
462        self._anonymous.addoption(*opts, **attrs)
463
464    def parse(self, args, namespace=None):
465        from _pytest._argcomplete import try_argcomplete
466        self.optparser = self._getparser()
467        try_argcomplete(self.optparser)
468        return self.optparser.parse_args([str(x) for x in args], namespace=namespace)
469
470    def _getparser(self):
471        from _pytest._argcomplete import filescompleter
472        optparser = MyOptionParser(self, self.extra_info)
473        groups = self._groups + [self._anonymous]
474        for group in groups:
475            if group.options:
476                desc = group.description or group.name
477                arggroup = optparser.add_argument_group(desc)
478                for option in group.options:
479                    n = option.names()
480                    a = option.attrs()
481                    arggroup.add_argument(*n, **a)
482        # bash like autocompletion for dirs (appending '/')
483        optparser.add_argument(FILE_OR_DIR, nargs='*').completer=filescompleter
484        return optparser
485
486    def parse_setoption(self, args, option, namespace=None):
487        parsedoption = self.parse(args, namespace=namespace)
488        for name, value in parsedoption.__dict__.items():
489            setattr(option, name, value)
490        return getattr(parsedoption, FILE_OR_DIR)
491
492    def parse_known_args(self, args, namespace=None):
493        """parses and returns a namespace object with known arguments at this
494        point.
495        """
496        return self.parse_known_and_unknown_args(args, namespace=namespace)[0]
497
498    def parse_known_and_unknown_args(self, args, namespace=None):
499        """parses and returns a namespace object with known arguments, and
500        the remaining arguments unknown at this point.
501        """
502        optparser = self._getparser()
503        args = [str(x) for x in args]
504        return optparser.parse_known_args(args, namespace=namespace)
505
506    def addini(self, name, help, type=None, default=None):
507        """ register an ini-file option.
508
509        :name: name of the ini-variable
510        :type: type of the variable, can be ``pathlist``, ``args``, ``linelist``
511               or ``bool``.
512        :default: default value if no ini-file option exists but is queried.
513
514        The value of ini-variables can be retrieved via a call to
515        :py:func:`config.getini(name) <_pytest.config.Config.getini>`.
516        """
517        assert type in (None, "pathlist", "args", "linelist", "bool")
518        self._inidict[name] = (help, type, default)
519        self._ininames.append(name)
520
521
522class ArgumentError(Exception):
523    """
524    Raised if an Argument instance is created with invalid or
525    inconsistent arguments.
526    """
527
528    def __init__(self, msg, option):
529        self.msg = msg
530        self.option_id = str(option)
531
532    def __str__(self):
533        if self.option_id:
534            return "option %s: %s" % (self.option_id, self.msg)
535        else:
536            return self.msg
537
538
539class Argument:
540    """class that mimics the necessary behaviour of optparse.Option """
541    _typ_map = {
542        'int': int,
543        'string': str,
544        }
545    # enable after some grace period for plugin writers
546    TYPE_WARN = False
547
548    def __init__(self, *names, **attrs):
549        """store parms in private vars for use in add_argument"""
550        self._attrs = attrs
551        self._short_opts = []
552        self._long_opts = []
553        self.dest = attrs.get('dest')
554        if self.TYPE_WARN:
555            try:
556                help = attrs['help']
557                if '%default' in help:
558                    warnings.warn(
559                        'pytest now uses argparse. "%default" should be'
560                        ' changed to "%(default)s" ',
561                        FutureWarning,
562                        stacklevel=3)
563            except KeyError:
564                pass
565        try:
566            typ = attrs['type']
567        except KeyError:
568            pass
569        else:
570            # this might raise a keyerror as well, don't want to catch that
571            if isinstance(typ, py.builtin._basestring):
572                if typ == 'choice':
573                    if self.TYPE_WARN:
574                        warnings.warn(
575                            'type argument to addoption() is a string %r.'
576                            ' For parsearg this is optional and when supplied '
577                            ' should be a type.'
578                            ' (options: %s)' % (typ, names),
579                            FutureWarning,
580                            stacklevel=3)
581                    # argparse expects a type here take it from
582                    # the type of the first element
583                    attrs['type'] = type(attrs['choices'][0])
584                else:
585                    if self.TYPE_WARN:
586                        warnings.warn(
587                            'type argument to addoption() is a string %r.'
588                            ' For parsearg this should be a type.'
589                            ' (options: %s)' % (typ, names),
590                            FutureWarning,
591                            stacklevel=3)
592                    attrs['type'] = Argument._typ_map[typ]
593                # used in test_parseopt -> test_parse_defaultgetter
594                self.type = attrs['type']
595            else:
596                self.type = typ
597        try:
598            # attribute existence is tested in Config._processopt
599            self.default = attrs['default']
600        except KeyError:
601            pass
602        self._set_opt_strings(names)
603        if not self.dest:
604            if self._long_opts:
605                self.dest = self._long_opts[0][2:].replace('-', '_')
606            else:
607                try:
608                    self.dest = self._short_opts[0][1:]
609                except IndexError:
610                    raise ArgumentError(
611                        'need a long or short option', self)
612
613    def names(self):
614        return self._short_opts + self._long_opts
615
616    def attrs(self):
617        # update any attributes set by processopt
618        attrs = 'default dest help'.split()
619        if self.dest:
620            attrs.append(self.dest)
621        for attr in attrs:
622            try:
623                self._attrs[attr] = getattr(self, attr)
624            except AttributeError:
625                pass
626        if self._attrs.get('help'):
627            a = self._attrs['help']
628            a = a.replace('%default', '%(default)s')
629            #a = a.replace('%prog', '%(prog)s')
630            self._attrs['help'] = a
631        return self._attrs
632
633    def _set_opt_strings(self, opts):
634        """directly from optparse
635
636        might not be necessary as this is passed to argparse later on"""
637        for opt in opts:
638            if len(opt) < 2:
639                raise ArgumentError(
640                    "invalid option string %r: "
641                    "must be at least two characters long" % opt, self)
642            elif len(opt) == 2:
643                if not (opt[0] == "-" and opt[1] != "-"):
644                    raise ArgumentError(
645                        "invalid short option string %r: "
646                        "must be of the form -x, (x any non-dash char)" % opt,
647                        self)
648                self._short_opts.append(opt)
649            else:
650                if not (opt[0:2] == "--" and opt[2] != "-"):
651                    raise ArgumentError(
652                        "invalid long option string %r: "
653                        "must start with --, followed by non-dash" % opt,
654                        self)
655                self._long_opts.append(opt)
656
657    def __repr__(self):
658        retval = 'Argument('
659        if self._short_opts:
660            retval += '_short_opts: ' + repr(self._short_opts) + ', '
661        if self._long_opts:
662            retval += '_long_opts: ' + repr(self._long_opts) + ', '
663        retval += 'dest: ' + repr(self.dest) + ', '
664        if hasattr(self, 'type'):
665            retval += 'type: ' + repr(self.type) + ', '
666        if hasattr(self, 'default'):
667            retval += 'default: ' + repr(self.default) + ', '
668        if retval[-2:] == ', ':  # always long enough to test ("Argument(" )
669            retval = retval[:-2]
670        retval += ')'
671        return retval
672
673
674class OptionGroup:
675    def __init__(self, name, description="", parser=None):
676        self.name = name
677        self.description = description
678        self.options = []
679        self.parser = parser
680
681    def addoption(self, *optnames, **attrs):
682        """ add an option to this group.
683
684        if a shortened version of a long option is specified it will
685        be suppressed in the help. addoption('--twowords', '--two-words')
686        results in help showing '--two-words' only, but --twowords gets
687        accepted **and** the automatic destination is in args.twowords
688        """
689        option = Argument(*optnames, **attrs)
690        self._addoption_instance(option, shortupper=False)
691
692    def _addoption(self, *optnames, **attrs):
693        option = Argument(*optnames, **attrs)
694        self._addoption_instance(option, shortupper=True)
695
696    def _addoption_instance(self, option, shortupper=False):
697        if not shortupper:
698            for opt in option._short_opts:
699                if opt[0] == '-' and opt[1].islower():
700                    raise ValueError("lowercase shortoptions reserved")
701        if self.parser:
702            self.parser.processoption(option)
703        self.options.append(option)
704
705
706class MyOptionParser(argparse.ArgumentParser):
707    def __init__(self, parser, extra_info=None):
708        if not extra_info:
709            extra_info = {}
710        self._parser = parser
711        argparse.ArgumentParser.__init__(self, usage=parser._usage,
712            add_help=False, formatter_class=DropShorterLongHelpFormatter)
713        # extra_info is a dict of (param -> value) to display if there's
714        # an usage error to provide more contextual information to the user
715        self.extra_info = extra_info
716
717    def parse_args(self, args=None, namespace=None):
718        """allow splitting of positional arguments"""
719        args, argv = self.parse_known_args(args, namespace)
720        if argv:
721            for arg in argv:
722                if arg and arg[0] == '-':
723                    lines = ['unrecognized arguments: %s' % (' '.join(argv))]
724                    for k, v in sorted(self.extra_info.items()):
725                        lines.append('  %s: %s' % (k, v))
726                    self.error('\n'.join(lines))
727            getattr(args, FILE_OR_DIR).extend(argv)
728        return args
729
730
731class DropShorterLongHelpFormatter(argparse.HelpFormatter):
732    """shorten help for long options that differ only in extra hyphens
733
734    - collapse **long** options that are the same except for extra hyphens
735    - special action attribute map_long_option allows surpressing additional
736      long options
737    - shortcut if there are only two options and one of them is a short one
738    - cache result on action object as this is called at least 2 times
739    """
740    def _format_action_invocation(self, action):
741        orgstr = argparse.HelpFormatter._format_action_invocation(self, action)
742        if orgstr and orgstr[0] != '-': # only optional arguments
743            return orgstr
744        res = getattr(action, '_formatted_action_invocation', None)
745        if res:
746            return res
747        options = orgstr.split(', ')
748        if len(options) == 2 and (len(options[0]) == 2 or len(options[1]) == 2):
749            # a shortcut for '-h, --help' or '--abc', '-a'
750            action._formatted_action_invocation = orgstr
751            return orgstr
752        return_list = []
753        option_map =  getattr(action, 'map_long_option', {})
754        if option_map is None:
755            option_map = {}
756        short_long = {}
757        for option in options:
758            if len(option) == 2 or option[2] == ' ':
759                continue
760            if not option.startswith('--'):
761                raise ArgumentError('long optional argument without "--": [%s]'
762                                    % (option), self)
763            xxoption = option[2:]
764            if xxoption.split()[0] not in option_map:
765                shortened = xxoption.replace('-', '')
766                if shortened not in short_long or \
767                   len(short_long[shortened]) < len(xxoption):
768                    short_long[shortened] = xxoption
769        # now short_long has been filled out to the longest with dashes
770        # **and** we keep the right option ordering from add_argument
771        for option in options: #
772            if len(option) == 2 or option[2] == ' ':
773                return_list.append(option)
774            if option[2:] == short_long.get(option.replace('-', '')):
775                return_list.append(option.replace(' ', '='))
776        action._formatted_action_invocation = ', '.join(return_list)
777        return action._formatted_action_invocation
778
779
780
781def _ensure_removed_sysmodule(modname):
782    try:
783        del sys.modules[modname]
784    except KeyError:
785        pass
786
787class CmdOptions(object):
788    """ holds cmdline options as attributes."""
789    def __init__(self, values=()):
790        self.__dict__.update(values)
791    def __repr__(self):
792        return "<CmdOptions %r>" %(self.__dict__,)
793    def copy(self):
794        return CmdOptions(self.__dict__)
795
796class Notset:
797    def __repr__(self):
798        return "<NOTSET>"
799
800notset = Notset()
801FILE_OR_DIR = 'file_or_dir'
802
803class Config(object):
804    """ access to configuration values, pluginmanager and plugin hooks.  """
805
806    def __init__(self, pluginmanager):
807        #: access to command line option as attributes.
808        #: (deprecated), use :py:func:`getoption() <_pytest.config.Config.getoption>` instead
809        self.option = CmdOptions()
810        _a = FILE_OR_DIR
811        self._parser = Parser(
812            usage="%%(prog)s [options] [%s] [%s] [...]" % (_a, _a),
813            processopt=self._processopt,
814        )
815        #: a pluginmanager instance
816        self.pluginmanager = pluginmanager
817        self.trace = self.pluginmanager.trace.root.get("config")
818        self.hook = self.pluginmanager.hook
819        self._inicache = {}
820        self._opt2dest = {}
821        self._cleanup = []
822        self._warn = self.pluginmanager._warn
823        self.pluginmanager.register(self, "pytestconfig")
824        self._configured = False
825        def do_setns(dic):
826            import pytest
827            setns(pytest, dic)
828        self.hook.pytest_namespace.call_historic(do_setns, {})
829        self.hook.pytest_addoption.call_historic(kwargs=dict(parser=self._parser))
830
831    def add_cleanup(self, func):
832        """ Add a function to be called when the config object gets out of
833        use (usually coninciding with pytest_unconfigure)."""
834        self._cleanup.append(func)
835
836    def _do_configure(self):
837        assert not self._configured
838        self._configured = True
839        self.hook.pytest_configure.call_historic(kwargs=dict(config=self))
840
841    def _ensure_unconfigure(self):
842        if self._configured:
843            self._configured = False
844            self.hook.pytest_unconfigure(config=self)
845            self.hook.pytest_configure._call_history = []
846        while self._cleanup:
847            fin = self._cleanup.pop()
848            fin()
849
850    def warn(self, code, message, fslocation=None):
851        """ generate a warning for this test session. """
852        self.hook.pytest_logwarning.call_historic(kwargs=dict(
853            code=code, message=message,
854            fslocation=fslocation, nodeid=None))
855
856    def get_terminal_writer(self):
857        return self.pluginmanager.get_plugin("terminalreporter")._tw
858
859    def pytest_cmdline_parse(self, pluginmanager, args):
860        # REF1 assert self == pluginmanager.config, (self, pluginmanager.config)
861        self.parse(args)
862        return self
863
864    def notify_exception(self, excinfo, option=None):
865        if option and option.fulltrace:
866            style = "long"
867        else:
868            style = "native"
869        excrepr = excinfo.getrepr(funcargs=True,
870            showlocals=getattr(option, 'showlocals', False),
871            style=style,
872        )
873        res = self.hook.pytest_internalerror(excrepr=excrepr,
874                                             excinfo=excinfo)
875        if not py.builtin.any(res):
876            for line in str(excrepr).split("\n"):
877                sys.stderr.write("INTERNALERROR> %s\n" %line)
878                sys.stderr.flush()
879
880    def cwd_relative_nodeid(self, nodeid):
881        # nodeid's are relative to the rootpath, compute relative to cwd
882        if self.invocation_dir != self.rootdir:
883            fullpath = self.rootdir.join(nodeid)
884            nodeid = self.invocation_dir.bestrelpath(fullpath)
885        return nodeid
886
887    @classmethod
888    def fromdictargs(cls, option_dict, args):
889        """ constructor useable for subprocesses. """
890        config = get_config()
891        config.option.__dict__.update(option_dict)
892        config.parse(args, addopts=False)
893        for x in config.option.plugins:
894            config.pluginmanager.consider_pluginarg(x)
895        return config
896
897    def _processopt(self, opt):
898        for name in opt._short_opts + opt._long_opts:
899            self._opt2dest[name] = opt.dest
900
901        if hasattr(opt, 'default') and opt.dest:
902            if not hasattr(self.option, opt.dest):
903                setattr(self.option, opt.dest, opt.default)
904
905    @hookimpl(trylast=True)
906    def pytest_load_initial_conftests(self, early_config):
907        self.pluginmanager._set_initial_conftests(early_config.known_args_namespace)
908
909    def _initini(self, args):
910        ns, unknown_args = self._parser.parse_known_and_unknown_args(args, namespace=self.option.copy())
911        r = determine_setup(ns.inifilename, ns.file_or_dir + unknown_args)
912        self.rootdir, self.inifile, self.inicfg = r
913        self._parser.extra_info['rootdir'] = self.rootdir
914        self._parser.extra_info['inifile'] = self.inifile
915        self.invocation_dir = py.path.local()
916        self._parser.addini('addopts', 'extra command line options', 'args')
917        self._parser.addini('minversion', 'minimally required pytest version')
918
919    def _preparse(self, args, addopts=True):
920        self._initini(args)
921        if addopts:
922            args[:] = shlex.split(os.environ.get('PYTEST_ADDOPTS', '')) + args
923            args[:] = self.getini("addopts") + args
924        self._checkversion()
925        self.pluginmanager.consider_preparse(args)
926        try:
927            self.pluginmanager.load_setuptools_entrypoints("pytest11")
928        except ImportError as e:
929            self.warn("I2", "could not load setuptools entry import: %s" % (e,))
930        self.pluginmanager.consider_env()
931        self.known_args_namespace = ns = self._parser.parse_known_args(args, namespace=self.option.copy())
932        if self.known_args_namespace.confcutdir is None and self.inifile:
933            confcutdir = py.path.local(self.inifile).dirname
934            self.known_args_namespace.confcutdir = confcutdir
935        try:
936            self.hook.pytest_load_initial_conftests(early_config=self,
937                    args=args, parser=self._parser)
938        except ConftestImportFailure:
939            e = sys.exc_info()[1]
940            if ns.help or ns.version:
941                # we don't want to prevent --help/--version to work
942                # so just let is pass and print a warning at the end
943                self._warn("could not load initial conftests (%s)\n" % e.path)
944            else:
945                raise
946
947    def _checkversion(self):
948        import pytest
949        minver = self.inicfg.get('minversion', None)
950        if minver:
951            ver = minver.split(".")
952            myver = pytest.__version__.split(".")
953            if myver < ver:
954                raise pytest.UsageError(
955                    "%s:%d: requires pytest-%s, actual pytest-%s'" %(
956                    self.inicfg.config.path, self.inicfg.lineof('minversion'),
957                    minver, pytest.__version__))
958
959    def parse(self, args, addopts=True):
960        # parse given cmdline arguments into this config object.
961        assert not hasattr(self, 'args'), (
962                "can only parse cmdline args at most once per Config object")
963        self._origargs = args
964        self.hook.pytest_addhooks.call_historic(
965                                  kwargs=dict(pluginmanager=self.pluginmanager))
966        self._preparse(args, addopts=addopts)
967        # XXX deprecated hook:
968        self.hook.pytest_cmdline_preparse(config=self, args=args)
969        args = self._parser.parse_setoption(args, self.option, namespace=self.option)
970        if not args:
971            cwd = os.getcwd()
972            if cwd == self.rootdir:
973                args = self.getini('testpaths')
974            if not args:
975                args = [cwd]
976        self.args = args
977
978    def addinivalue_line(self, name, line):
979        """ add a line to an ini-file option. The option must have been
980        declared but might not yet be set in which case the line becomes the
981        the first line in its value. """
982        x = self.getini(name)
983        assert isinstance(x, list)
984        x.append(line) # modifies the cached list inline
985
986    def getini(self, name):
987        """ return configuration value from an :ref:`ini file <inifiles>`. If the
988        specified name hasn't been registered through a prior
989        :py:func:`parser.addini <pytest.config.Parser.addini>`
990        call (usually from a plugin), a ValueError is raised. """
991        try:
992            return self._inicache[name]
993        except KeyError:
994            self._inicache[name] = val = self._getini(name)
995            return val
996
997    def _getini(self, name):
998        try:
999            description, type, default = self._parser._inidict[name]
1000        except KeyError:
1001            raise ValueError("unknown configuration value: %r" %(name,))
1002        try:
1003            value = self.inicfg[name]
1004        except KeyError:
1005            if default is not None:
1006                return default
1007            if type is None:
1008                return ''
1009            return []
1010        if type == "pathlist":
1011            dp = py.path.local(self.inicfg.config.path).dirpath()
1012            l = []
1013            for relpath in shlex.split(value):
1014                l.append(dp.join(relpath, abs=True))
1015            return l
1016        elif type == "args":
1017            return shlex.split(value)
1018        elif type == "linelist":
1019            return [t for t in map(lambda x: x.strip(), value.split("\n")) if t]
1020        elif type == "bool":
1021            return bool(_strtobool(value.strip()))
1022        else:
1023            assert type is None
1024            return value
1025
1026    def _getconftest_pathlist(self, name, path):
1027        try:
1028            mod, relroots = self.pluginmanager._rget_with_confmod(name, path)
1029        except KeyError:
1030            return None
1031        modpath = py.path.local(mod.__file__).dirpath()
1032        l = []
1033        for relroot in relroots:
1034            if not isinstance(relroot, py.path.local):
1035                relroot = relroot.replace("/", py.path.local.sep)
1036                relroot = modpath.join(relroot, abs=True)
1037            l.append(relroot)
1038        return l
1039
1040    def getoption(self, name, default=notset, skip=False):
1041        """ return command line option value.
1042
1043        :arg name: name of the option.  You may also specify
1044            the literal ``--OPT`` option instead of the "dest" option name.
1045        :arg default: default value if no option of that name exists.
1046        :arg skip: if True raise pytest.skip if option does not exists
1047            or has a None value.
1048        """
1049        name = self._opt2dest.get(name, name)
1050        try:
1051            val = getattr(self.option, name)
1052            if val is None and skip:
1053                raise AttributeError(name)
1054            return val
1055        except AttributeError:
1056            if default is not notset:
1057                return default
1058            if skip:
1059                import pytest
1060                pytest.skip("no %r option found" %(name,))
1061            raise ValueError("no option named %r" % (name,))
1062
1063    def getvalue(self, name, path=None):
1064        """ (deprecated, use getoption()) """
1065        return self.getoption(name)
1066
1067    def getvalueorskip(self, name, path=None):
1068        """ (deprecated, use getoption(skip=True)) """
1069        return self.getoption(name, skip=True)
1070
1071def exists(path, ignore=EnvironmentError):
1072    try:
1073        return path.check()
1074    except ignore:
1075        return False
1076
1077def getcfg(args, inibasenames):
1078    args = [x for x in args if not str(x).startswith("-")]
1079    if not args:
1080        args = [py.path.local()]
1081    for arg in args:
1082        arg = py.path.local(arg)
1083        for base in arg.parts(reverse=True):
1084            for inibasename in inibasenames:
1085                p = base.join(inibasename)
1086                if exists(p):
1087                    iniconfig = py.iniconfig.IniConfig(p)
1088                    if 'pytest' in iniconfig.sections:
1089                        return base, p, iniconfig['pytest']
1090                    elif inibasename == "pytest.ini":
1091                        # allowed to be empty
1092                        return base, p, {}
1093    return None, None, None
1094
1095
1096def get_common_ancestor(args):
1097    # args are what we get after early command line parsing (usually
1098    # strings, but can be py.path.local objects as well)
1099    common_ancestor = None
1100    for arg in args:
1101        if str(arg)[0] == "-":
1102            continue
1103        p = py.path.local(arg)
1104        if common_ancestor is None:
1105            common_ancestor = p
1106        else:
1107            if p.relto(common_ancestor) or p == common_ancestor:
1108                continue
1109            elif common_ancestor.relto(p):
1110                common_ancestor = p
1111            else:
1112                shared = p.common(common_ancestor)
1113                if shared is not None:
1114                    common_ancestor = shared
1115    if common_ancestor is None:
1116        common_ancestor = py.path.local()
1117    elif not common_ancestor.isdir():
1118        common_ancestor = common_ancestor.dirpath()
1119    return common_ancestor
1120
1121
1122def determine_setup(inifile, args):
1123    if inifile:
1124        iniconfig = py.iniconfig.IniConfig(inifile)
1125        try:
1126            inicfg = iniconfig["pytest"]
1127        except KeyError:
1128            inicfg = None
1129        rootdir = get_common_ancestor(args)
1130    else:
1131        ancestor = get_common_ancestor(args)
1132        rootdir, inifile, inicfg = getcfg(
1133            [ancestor], ["pytest.ini", "tox.ini", "setup.cfg"])
1134        if rootdir is None:
1135            for rootdir in ancestor.parts(reverse=True):
1136                if rootdir.join("setup.py").exists():
1137                    break
1138            else:
1139                rootdir = ancestor
1140    return rootdir, inifile, inicfg or {}
1141
1142
1143def setns(obj, dic):
1144    import pytest
1145    for name, value in dic.items():
1146        if isinstance(value, dict):
1147            mod = getattr(obj, name, None)
1148            if mod is None:
1149                modname = "pytest.%s" % name
1150                mod = types.ModuleType(modname)
1151                sys.modules[modname] = mod
1152                mod.__all__ = []
1153                setattr(obj, name, mod)
1154            obj.__all__.append(name)
1155            setns(mod, value)
1156        else:
1157            setattr(obj, name, value)
1158            obj.__all__.append(name)
1159            #if obj != pytest:
1160            #    pytest.__all__.append(name)
1161            setattr(pytest, name, value)
1162
1163
1164def create_terminal_writer(config, *args, **kwargs):
1165    """Create a TerminalWriter instance configured according to the options
1166    in the config object. Every code which requires a TerminalWriter object
1167    and has access to a config object should use this function.
1168    """
1169    tw = py.io.TerminalWriter(*args, **kwargs)
1170    if config.option.color == 'yes':
1171        tw.hasmarkup = True
1172    if config.option.color == 'no':
1173        tw.hasmarkup = False
1174    return tw
1175
1176
1177def _strtobool(val):
1178    """Convert a string representation of truth to true (1) or false (0).
1179
1180    True values are 'y', 'yes', 't', 'true', 'on', and '1'; false values
1181    are 'n', 'no', 'f', 'false', 'off', and '0'.  Raises ValueError if
1182    'val' is anything else.
1183
1184    .. note:: copied from distutils.util
1185    """
1186    val = val.lower()
1187    if val in ('y', 'yes', 't', 'true', 'on', '1'):
1188        return 1
1189    elif val in ('n', 'no', 'f', 'false', 'off', '0'):
1190        return 0
1191    else:
1192        raise ValueError("invalid truth value %r" % (val,))
1193