~anitanayak/charms/trusty/ibm-mq/ibm-mq-trusty

« back to all changes in this revision

Viewing changes to .tox/py35/lib/python3.5/site-packages/_pytest/config.py

  • Committer: Anita Nayak
  • Date: 2016-10-24 07:10:08 UTC
  • Revision ID: anitanayak@in.ibm.com-20161024071008-tqk3cefak6nc1c69
checking in after fixing lint errors

Show diffs side-by-side

added added

removed removed

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