c99b5590c79b392db65b1ebbf2c23585f784acfc
[idea/community.git] / python / helpers / pycharm / _jb_tox_runner.py
1 # coding=utf-8
2 """
3 Runs tox from current directory.
4 It supports any runner, but well-known runners (py.test and unittest) are switched to our internal runners to provide
5 better support
6 """
7 import os
8 import sys
9
10 from tox import config as tox_config, session as tox_session
11 from tox.session import Reporter
12
13 from tcmessages import TeamcityServiceMessages
14
15 helpers_dir = str(os.path.split(__file__)[0])
16
17
18 class _Unit2(object):
19     def fix(self, command, dir_to_run, bin):
20         if command[0] == "unit2":
21             return [bin, os.path.join(helpers_dir, "utrunner.py"), dir_to_run] + command[1:] + ["true"]
22         elif command == ["python", "-m", "unittest", "discover"]:
23             return [bin, os.path.join(helpers_dir, "utrunner.py"), dir_to_run, "true"]
24         return None
25
26
27 class _PyTest(object):
28     def fix(self, command, dir_to_run, bin):
29         if command[0] != "py.test":
30             return None
31         normal_path = os.path.normpath(dir_to_run) + os.sep
32         return [bin, os.path.join(helpers_dir, "pytestrunner.py"), "-p", "pytest_teamcity", normal_path] + command[1:]
33
34
35 class _Nose(object):
36     def fix(self, command, dir_to_run, bin):
37         if command[0] != "nosetests":
38             return None
39         return [bin, os.path.join(helpers_dir, "noserunner.py"), dir_to_run] + command[1:]
40
41
42
43 _RUNNERS = [_Unit2(), _PyTest(), _Nose()]
44
45 teamcity = TeamcityServiceMessages()
46
47
48 class _Reporter(Reporter):
49     def logaction_start(self, action):
50         super(_Reporter, self).logaction_start(action)
51         if action.activity == "getenv":
52             teamcity.output.write("\n")
53             teamcity.testSuiteStarted(action.id, location="tox_env://" + str(action.id))
54             self.current_suite = action.id
55
56     def logaction_finish(self, action):
57         super(_Reporter, self).logaction_finish(action)
58         if action.activity == "runtests":
59             teamcity.testSuiteFinished(action.id)
60             teamcity.output.write("\n")
61
62     def error(self, msg):
63         super(_Reporter, self).error(msg)
64         name = teamcity.current_test_name()
65         if name:
66             if name != teamcity.topmost_suite:
67                 teamcity.testFailed(name, msg)
68             else:
69                 teamcity.testFailed("ERROR", msg)
70                 teamcity.testSuiteFinished(name)
71         else:
72             sys.stderr.write(msg)
73
74     def skip(self, msg):
75         super(_Reporter, self).skip(msg)
76         name = teamcity.current_test_name()
77         if name:
78             teamcity.testFinished(name)
79
80
81 config = tox_config.parseconfig()
82 for env, tmp_config in config.envconfigs.items():
83     if not tmp_config.setenv:
84         tmp_config.setenv = dict()
85     tmp_config.setenv["_jb_do_not_call_enter_matrix"] = "1"
86     commands = tmp_config.commands
87     if not isinstance(commands, list) or not len(commands):
88         continue
89     for fixer in _RUNNERS:
90         _env = config.envconfigs[env]
91         dir_to_run = str(_env.changedir)
92         for i, command in enumerate(commands):
93             fixed_command = fixer.fix(command, dir_to_run, str(_env.envpython))
94             if fixed_command:
95                 commands[i] = fixed_command
96     tmp_config.commands = commands
97
98 session = tox_session.Session(config, Report=_Reporter)
99 teamcity.testMatrixEntered()
100 session.runcommand()