-
Notifications
You must be signed in to change notification settings - Fork 54
/
config.py
120 lines (87 loc) · 3.08 KB
/
config.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
from __future__ import print_function
import sys
import pytest
from .util import silence
try:
from configparser import ConfigParser
except ImportError:
from ConfigParser import ConfigParser
from .constants import EXIT_INTERRUPTED, EXIT_NOTESTSCOLLECTED, EXIT_OK
CLI_OPTION_PREFIX = '--'
class CollectError(Exception):
pass
class StopCollect(Exception):
pass
class CollectConfig(object):
"""
A pytest plugin to gets the configuration file.
"""
def __init__(self):
self.path = None
def pytest_cmdline_main(self, config):
if hasattr(config, 'inifile'):
# pytest >= 2.7.0
inifile = config.inifile
else:
# pytest < 2.7.0
inifile = config.inicfg.config.path
if inifile:
self.path = str(inifile)
raise StopCollect()
def _run_pytest_collect(pytest_args):
collect_config_plugin = CollectConfig()
argv = pytest_args + ['--collect-only']
try:
exit_code = pytest.main(argv, plugins=[collect_config_plugin])
except StopCollect:
return collect_config_plugin.path
if exit_code == EXIT_INTERRUPTED:
# pytest raises EXIT_INTERRUPTED on *both* keyboard error and parse errors
raise KeyboardInterrupt()
if exit_code not in [EXIT_OK, EXIT_NOTESTSCOLLECTED]:
raise CollectError()
return collect_config_plugin.path
def _collect_config(pytest_args, silent=True):
if silent:
try:
with silence():
return _run_pytest_collect(pytest_args)
except (KeyboardInterrupt, Exception, SystemExit):
pass
# Print message and run again without silencing
print('Error: Could not run --collect-only to handle the pytest '
'config file. Trying again without silencing output...',
file=sys.stderr)
# Collect without silencing
return _run_pytest_collect(pytest_args)
def merge_config(args, pytest_args, silent=True, verbose=False):
if verbose:
print('Locating inifile...')
try:
config_path = _collect_config(pytest_args, silent)
except (KeyboardInterrupt, CollectError):
return False
if not config_path:
return True
config = ConfigParser()
config.read(config_path)
if not config.has_section('pytest-watch'):
return True
for cli_name in args:
if not cli_name.startswith(CLI_OPTION_PREFIX):
continue
config_name = cli_name[len(CLI_OPTION_PREFIX):]
# Let CLI options take precedence
if args[cli_name]:
continue
# Find config option
if not config.has_option('pytest-watch', config_name):
continue
# Merge config option using the expected type
if isinstance(args[cli_name], list):
args[cli_name].append(config.get('pytest-watch', config_name))
elif isinstance(args[cli_name], bool):
args[cli_name] = config.getboolean('pytest-watch', config_name)
else:
args[cli_name] = config.get('pytest-watch', config_name)
return True